package ee.siimkaspar.subjects.model;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.PrePersist;
import javax.persistence.PreUpdate;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;

import org.apache.log4j.Logger;
import org.codehaus.jackson.annotate.JsonIgnoreProperties;

import com.opensymphony.xwork2.ActionContext;

import ee.siimkaspar.subjects.service.BaseService;
import ee.siimkaspar.subjects.util.Const;

@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
@Entity
@Table(name = "person")
public class Person implements Serializable, ModelInterface {

	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	@Column(name = "person", unique = true, nullable = false)
	private Integer id;
	@ManyToOne(fetch = FetchType.LAZY)
	@JoinColumn(name = "updated_by")
	private Employee employeeByUpdatedBy;
	@ManyToOne(fetch = FetchType.LAZY)
	@JoinColumn(name = "created_by")
	private Employee employeeByCreatedBy;
	@Column(name = "first_name", length = 100)
	private String firstName;
	@Column(name = "last_name", length = 100)
	private String lastName;
	@Column(name = "identity_code", length = 20)
	private String identityCode;
	@Temporal(TemporalType.DATE)
	@Column(name = "birth_date", length = 13)
	private Date birthDate;
	@Temporal(TemporalType.TIMESTAMP)
	@Column(name = "created", length = 29)
	private Date created;
	@Temporal(TemporalType.TIMESTAMP)
	@Column(name = "updated", length = 29)
	private Date updated;
	@OneToMany(fetch = FetchType.LAZY, mappedBy = "person")
	private List<EnterprisePersonRelation> enterprisePersonRelations = new ArrayList<EnterprisePersonRelation>();
	@OneToMany(fetch = FetchType.LAZY, mappedBy = "person")
	private List<Employee> employees = new ArrayList<Employee>();

	public Person() {
	}

	public Person(String firstName, String lastName, String identityCode,
			Date birthDate) {
		super();
		this.firstName = firstName;
		this.lastName = lastName;
		this.identityCode = identityCode;
		this.birthDate = birthDate;
	}
	
	@PreUpdate
    @PrePersist
    public void updateMetadata() {
        setUpdated(new Date());
        if (getCreated()==null) {
        	setCreated(new Date());
        }
        Map<String, Object> session = ActionContext.getContext().getSession();
        if (session != null) {
            Employee p = ((UserAccount) session.get(Const.SESSION_USER)).getEmployeeBySubjectFk();
            if (p != null) {
            	setEmployeeByUpdatedBy(p);
            	if (getEmployeeByCreatedBy() == null) {
            		setEmployeeByCreatedBy(p);
            	}
            }
        } else {
            Logger.getLogger(BaseService.class).warn("Session is null. Username not set.");
        }
    }

	public Integer getId() {
		return this.id;
	}

	public void setId(Integer id) {
		this.id = id;
	}

	public Employee getEmployeeByUpdatedBy() {
		return this.employeeByUpdatedBy;
	}

	public void setEmployeeByUpdatedBy(Employee employeeByUpdatedBy) {
		this.employeeByUpdatedBy = employeeByUpdatedBy;
	}

	public Employee getEmployeeByCreatedBy() {
		return this.employeeByCreatedBy;
	}

	public void setEmployeeByCreatedBy(Employee employeeByCreatedBy) {
		this.employeeByCreatedBy = employeeByCreatedBy;
	}

	public String getFirstName() {
		return this.firstName;
	}

	public void setFirstName(String firstName) {
		this.firstName = firstName;
	}

	public String getLastName() {
		return this.lastName;
	}

	public void setLastName(String lastName) {
		this.lastName = lastName;
	}

	public String getIdentityCode() {
		return this.identityCode;
	}

	public void setIdentityCode(String identityCode) {
		this.identityCode = identityCode;
	}

	public Date getBirthDate() {
		return this.birthDate;
	}

	public void setBirthDate(Date birthDate) {
		this.birthDate = birthDate;
	}
	
	public Date getCreated() {
		return this.created;
	}

	public void setCreated(Date created) {
		this.created = created;
	}

	public Date getUpdated() {
		return this.updated;
	}

	public void setUpdated(Date updated) {
		this.updated = updated;
	}

	public List<EnterprisePersonRelation> getEnterprisePersonRelations() {
		return enterprisePersonRelations;
	}

	public void setEnterprisePersonRelations(
			List<EnterprisePersonRelation> enterprisePersonRelations) {
		this.enterprisePersonRelations = enterprisePersonRelations;
	}

	public List<Employee> getEmployees() {
		return employees;
	}

	public void setEmployees(List<Employee> employees) {
		this.employees = employees;
	}

	@Override
	public String toString() {
		return "Person [id=" + id + ", firstName=" + firstName + ", lastName="
				+ lastName + "]";
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result
				+ ((firstName == null) ? 0 : firstName.hashCode());
		result = prime * result + ((id == null) ? 0 : id.hashCode());
		result = prime * result
				+ ((lastName == null) ? 0 : lastName.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Person other = (Person) obj;
		if (firstName == null) {
			if (other.firstName != null)
				return false;
		} else if (!firstName.equals(other.firstName))
			return false;
		if (id == null) {
			if (other.id != null)
				return false;
		} else if (!id.equals(other.id))
			return false;
		if (lastName == null) {
			if (other.lastName != null)
				return false;
		} else if (!lastName.equals(other.lastName))
			return false;
		return true;
	}
	@Override
	public boolean validate() {
		// TODO Auto-generated method stub
		return true;
	}
}
